home *** CD-ROM | disk | FTP | other *** search
/ AOL File Library: 2,801 to 2,900 / aol-file-protocol-4400-2801-to-2900.zip / AOLDLs / C++ Files Library / C++ Spline Class V 1.02 / C++ Spline Class 1.02.sea / Spline Class / 2DSpline.cp next >
Text File  |  1993-10-01  |  48KB  |  1,244 lines

  1. /************************************************************************************************/
  2. /*                                                         Chris Marshall                                                    */
  3. /*                                                                                                                                */
  4. /*                                                Nikon Electronic Imaging Dept                                            */
  5. /*                                                    1300 Walt Whitman Road                                                */
  6. /*                                                      Melville, NY 11747                                                    */
  7. /*                                                         (516) 547-4200                                                    */
  8. /*                                                                                                                                */
  9. /************************************************************************************************/
  10. /*        File Name:            2DSpline.cp                                                                                    */
  11. /*        Description:        Implementation file for a 2-dimensional B-spline class                        */
  12. /*        Primary Author:    Chris Marshall - from algorithm modified by Tom Knoll & Khouri Giordano    */
  13. /*        Version:                1.02                                                                                            */
  14. /*        Project:                Library file                                                                                */
  15. /*        Compiler(s):        Symantec C++ 6.0                                                                            */
  16. /************************************************************************************************/
  17. /*                                                     MODIFICATION HISTORY                                                */
  18. /************************************************************************************************/
  19. /*    Date            Author                Description                                                                        */
  20. /*                                                                                                                                */
  21. /*    09/30/93        Chris Marshall        I fixed a little bug in the coefficient calculator that made    */
  22. /*                                            the curve just the teensiest bit WRONG.                                */
  23. /*    10/01/93        Chris Marshall        I fixed another little bug in the coefficient calculator that    */
  24. /*                                            made the curve just the teensiest bit WRONG (floating point).    */
  25. /*                                                                                                                                */
  26. /************************************************************************************************/
  27. /* This class implements a basic B-spline (the kind that passes a curve through points, as        */
  28. /* opposed to around them).  Tom Knoll added the little hack for eliminating the need for            */
  29. /* points beyond the endpoints, Khouri did a port from Pascal, and I made it work for multiple    */
  30. /* dynamic points, and made it classy.                                                                                */
  31. /* Basically, it's a plain old spline, wrapped in a C++ class.  Since it's a limited spline        */
  32. /* algorithm, made almost exclusively for gamma table manipulation, I've taken the opprtunity    */
  33. /* to force the points to be added (and internally stored) into long integer form.  In most        */
  34. /* cases, this will not result in a loss of accuracy, and it makes the class much faster.  If    */
  35. /* this class is used in a non-FPU machine, it may be a wee bit on the sluggish side, so I        */
  36. /* suggest limiting the scope and number of data points in these cases.  This class will track    */
  37. /* a single, "selected" point, and has special methods for dealing with this point as a default    */
  38. /* destination for operations. Data points are stored in ascending X-axis order.  The two            */
  39. /* endpoints are considered to be the outside boundaries of the spline, and all xValues that        */
  40. /* are presented beyond the endpoints will be returned the endpoint's yValue.                            */
  41. /* There is a subclass, called "FixedSpline", that does all the calculations in fixed-point.        */
  42. /* It is quite optimized for speed, and will perform quite well.  Don't expect the same degree    */
  43. /* of accuracy from it, but for most cases (gamma table manipulation), this won't make any real    */
  44. /* difference.  It'll get you something, but its not a screamer if you have a sluggish machine.    */
  45. /* These classes could also be very useful for things like waveform and envelope manipulation.    */
  46. /************************************************************************************************/
  47.  
  48. #include    "2DSpline.h"
  49.  
  50. /************************************************************************************************/
  51. /*        Function Name:        Spline                                                                                        */
  52. /*        Description:        Initializes the object, and sets two locked endpoints                            */
  53. /*        Primary Author:    Tom Knoll, Khouri Giordano & Chris Marshall                                        */
  54. /************************************************************************************************/
  55. /*                                                    MODIFICATION HISTORY                                                    */
  56. /************************************************************************************************/
  57. /*    Date            Author                Description                                                                        */
  58. /*                                                                                                                                */
  59. /************************************************************************************************/
  60. /*##############################################################################################*/
  61. /************************************************************************************************/
  62.  
  63. Spline::Spline ( long x0, long y0, long x1, long y1, long hitRadius )
  64. {
  65.     this->Initialize ( );
  66.     this->AddSplinePoint ( x0, y0 );
  67.     this->AddSplinePoint ( x1, y1 );
  68.     fHitRadius = hitRadius;
  69. }
  70.  
  71. /************************************************************************************************/
  72. /*        Function Name:        CreateSplineCoefficients                                                                */
  73. /*        Description:        Calculates a table of spline coefficients for caculating a spline curve    */
  74. /*        Primary Author:    Tom Knoll, Khouri Giordano & Chris Marshall                                        */
  75. /************************************************************************************************/
  76. /*                                                    MODIFICATION HISTORY                                                    */
  77. /************************************************************************************************/
  78. /*    Date            Author                Description                                                                        */
  79. /*                                                                                                                                */
  80. /*    09/30/93        Chris Marshall        I fixed a little bug in the coefficient calculator that made    */
  81. /*                                            the curve just the teensiest bit WRONG.                                */
  82. /*    10/01/93        Chris Marshall        I fixed another little bug in the coefficient calculator that    */
  83. /*                                            made the curve just the teensiest bit WRONG.                            */
  84. /*                                                                                                                                */
  85. /************************************************************************************************/
  86. /*##############################################################################################*/
  87. /************************************************************************************************/
  88.  
  89. void Spline::CreateCoefficients ( )
  90. {
  91.     register short            count;
  92.     register long double    lastSlope, slope, temp;
  93.     long                        lastDeltaX, deltaX;
  94.     long                        size = (long)sizeof ( long double ) * (long)fNumPoints;
  95.     
  96.     if ( !size )
  97.         return;
  98.     
  99.     fNumPoints--;    // "Neck down" our point count by one
  100.  
  101.     lastDeltaX = *(*fXArray + 1) - **fXArray;
  102.     **fSlopeArray = lastSlope = (long double)(*(*fYArray + 1) - **fYArray)
  103.                                                             / (long double)lastDeltaX;
  104.     
  105.     for ( count = 2; count <= fNumPoints; ++count )
  106.         {
  107.         deltaX = *(*fXArray + count) - *(*fXArray + (count - 1));
  108.         slope = (long double)(*(*fYArray + count) - *(*fYArray + (count - 1)))
  109.                     / (long double)deltaX;
  110.         
  111.         *(*fSlopeArray + (count - 1)) = ((lastSlope * (long double)deltaX) + (slope
  112.                 * (long double)lastDeltaX)) / (long double)(lastDeltaX + deltaX);
  113.         lastDeltaX = deltaX;
  114.         lastSlope = slope;
  115.         }
  116.     
  117.     *(*fSlopeArray + fNumPoints) = (2 * lastSlope) - *(*fSlopeArray + (fNumPoints - 1));
  118.     **fSlopeArray = (2 * **fSlopeArray) - *(*fSlopeArray + 1);
  119.     
  120.     if ( fNumPoints > 2 )    // If we have more than three points, we invent endpoint derivatives
  121.         {
  122.         **fPAl2 = *(*fPAl1 + fNumPoints) = 0.5;
  123.         **fPAl3 = 0.75 * (**fSlopeArray + *(*fSlopeArray + 1));
  124.         *(*fPAl3 + fNumPoints) = 0.75 * (*(*fSlopeArray + (fNumPoints - 1))
  125.                 + *(*fSlopeArray + fNumPoints));
  126.         
  127.         for ( count = 1; count <= fNumPoints; ++count)    // Fixed an under count problem here
  128.             {
  129.             if ( count < fNumPoints )
  130.                 {
  131.                 temp = (long double)(*(*fXArray + (count + 1)) - *(*fXArray + (count - 1))) * 2.0;
  132.                 *(*fPAl1 + count) = (long double)(*(*fXArray + (count + 1)) - *(*fXArray + count))
  133.                         / temp;
  134.                 // A shortcut didn't work, so this is back
  135.                 *(*fPAl2 + count) = (long double)(*(*fXArray + count) - *(*fXArray + (count - 1)))
  136.                         / temp;
  137.                 *(*fPAl3 + count) = 1.5 * *(*fSlopeArray + count);
  138.                 }
  139.  
  140.             temp = (1 - (*(*fPAl2 + (count - 1)) * *(*fPAl1 + count)));
  141.             
  142.             if ( count < fNumPoints )
  143.                 *(*fPAl2 + count) = *(*fPAl2 + count) / temp;
  144.             
  145.             *(*fPAl3 + count) = (*(*fPAl3 + count) - *(*fPAl3 + (count - 1)) * *(*fPAl1 + count))
  146.                     / temp;
  147.             }
  148.         
  149.         for ( count = fNumPoints - 1; count >= 0; --count )
  150.             *(*fSlopeArray + count) = *(*fPAl3 + count) - (*(*fPAl2 + count)
  151.                                                 * *(*fPAl3 + (count + 1)));
  152.         
  153.         *(*fSlopeArray + fNumPoints) = *(*fPAl3 + fNumPoints);
  154.         }
  155.     
  156.     fNumPoints++;
  157. }
  158.  
  159. /************************************************************************************************/
  160. /*        Function Name:        Initialize                                                                                    */
  161. /*        Description:        Initializes the class' variables                                                        */
  162. /*        Primary Author:    Tom Knoll, Khouri Giordano & Chris Marshall                                        */
  163. /************************************************************************************************/
  164. /*                                                    MODIFICATION HISTORY                                                    */
  165. /************************************************************************************************/
  166. /*    Date            Author                Description                                                                        */
  167. /*                                                                                                                                */
  168. /************************************************************************************************/
  169. /*##############################################################################################*/
  170. /************************************************************************************************/
  171.  
  172. void Spline::Initialize ( )
  173. {
  174.     fNumPoints = 0;
  175.     fXArray = 0L;
  176.     fYArray = 0L;
  177.     fSlopeArray = 0L;
  178.     fHitRadius = 0;
  179.     fSelectedPoint = 0;
  180.     fPAl1 = fPAl2 = fPAl3 = 0L;
  181.     fAlloc = 0;
  182. }
  183.  
  184. /************************************************************************************************/
  185. /*        Function Name:        ~Spline                                                                                        */
  186. /*        Description:        Deallocates the arrays upon destruction of the object                            */
  187. /*        Primary Author:    Chris Marshall                                                                                */
  188. /************************************************************************************************/
  189. /*                                                    MODIFICATION HISTORY                                                    */
  190. /************************************************************************************************/
  191. /*    Date            Author                Description                                                                        */
  192. /*                                                                                                                                */
  193. /************************************************************************************************/
  194. /*##############################################################################################*/
  195. /************************************************************************************************/
  196.  
  197. Spline::~Spline ( )
  198. {
  199.     if ( fXArray )
  200.         DisposHandle ( (Handle)fXArray );
  201.     if ( fYArray )
  202.         DisposHandle ( (Handle)fYArray );
  203.     if ( fSlopeArray )
  204.         DisposHandle ( (Handle)fSlopeArray );
  205.     if ( fPAl3 )
  206.         DisposHandle ( (Handle)fPAl3 );
  207.     if ( fPAl2 )
  208.         DisposHandle ( (Handle)fPAl2 );
  209.     if ( fPAl1 )
  210.         DisposHandle ( (Handle)fPAl1 );
  211. }
  212.  
  213. /************************************************************************************************/
  214. /*        Function Name:        AddSplinePoint                                                                                */
  215. /*        Description:        Adds a point to the list of points, and recalculates the coefficients    */
  216. /*        Primary Author:    Chris Marshall                                                                                */
  217. /************************************************************************************************/
  218. /*                                                    MODIFICATION HISTORY                                                    */
  219. /************************************************************************************************/
  220. /*    Date            Author                Description                                                                        */
  221. /*                                                                                                                                */
  222. /************************************************************************************************/
  223. /*##############################################################################################*/
  224. /************************************************************************************************/
  225.  
  226. short Spline::AddSplinePoint ( long xValue, long yValue )
  227. {
  228.     short index = 0;
  229.     long    size = (fNumPoints + 1) * sizeof ( long );
  230.     long    sizeS = (fNumPoints + 1) * sizeof ( long double );
  231.     
  232.     if ( fNumPoints )
  233.         {
  234.         if ( !(index = this->IsASplinePoint ( xValue, yValue, true )) )
  235.             {
  236.             while ( (index < fNumPoints) && (xValue > *(*fXArray + index)) ) index++;
  237.             
  238.             if ( (index == fNumPoints) || (xValue != *(*fXArray + index)) )
  239.                 {
  240.                 SetHandleSize ( (Handle)fXArray, size );
  241.                 
  242.                 if ( MemError ( ) == noErr )
  243.                     SetHandleSize ( (Handle)fYArray, size );
  244.                 
  245.                 if ( MemError ( ) == noErr )
  246.                     SetHandleSize ( (Handle)fSlopeArray, sizeS );
  247.                 
  248.                 if ( MemError ( ) == noErr )
  249.                     {
  250.                     size = (fNumPoints - index) * sizeof ( long );
  251.                     sizeS = (fNumPoints - index) * sizeof ( long double );
  252.                     
  253.                     if ( size )
  254.                         {
  255.                         BlockMove ( (*fXArray + index), (*fXArray + 1 + index), size );
  256.                         BlockMove ( (*fYArray + index), (*fYArray + 1 + index), size );
  257.                         BlockMove ( (*fSlopeArray + index), (*fSlopeArray + 1 + index), sizeS );
  258.                         }
  259.                     
  260.                     *(*fXArray + index) = xValue;
  261.                     *(*fYArray + index) = yValue;
  262.                     
  263.                     fNumPoints++;
  264.                     
  265.                     fSelectedPoint = index + 1;
  266.                     
  267.                     // We need to add another block to our working buffers
  268.                     if ( (fNumPoints > fAlloc) && fPAl1 && fPAl2 && fPAl3 )
  269.                         {
  270.                         fAlloc += kInc;
  271.                         sizeS = fAlloc * sizeof ( long double );
  272.                         
  273.                         SetHandleSize ( (Handle)fPAl1, sizeS );
  274.                         
  275.                         if ( MemError ( ) == noErr )
  276.                             SetHandleSize ( (Handle)fPAl2, sizeS );
  277.                         
  278.                         if ( MemError ( ) == noErr )
  279.                             SetHandleSize ( (Handle)fPAl3, sizeS );
  280.                         }
  281.                     
  282.                     this->CreateCoefficients ( );
  283.                     }
  284.                 else
  285.                     index = -1;
  286.                 }
  287.             else
  288.                 {
  289.                 fSelectedPoint = index + 1;
  290.                 *(*fYArray + index) = yValue;
  291.                 }
  292.             }
  293.         else
  294.             fSelectedPoint = index + 1;
  295.         }
  296.     else
  297.         {
  298.         fXArray = (long**) NewHandle ( size );
  299.         
  300.         if ( fXArray )
  301.             {
  302.             fYArray = (long**) NewHandle ( size );
  303.             
  304.             if ( fYArray )
  305.                 {
  306.                 fSlopeArray = (long double**) NewHandle ( sizeS );
  307.                 
  308.                 if ( fSlopeArray )
  309.                     {
  310.                     fPAl1 = (long double**)NewHandle ( kInc * sizeof ( long double ) );
  311.                     
  312.                     if ( fPAl1 )
  313.                         {
  314.                         fPAl2 = (long double**)NewHandle ( kInc * sizeof ( long double ) );
  315.                         
  316.                         if ( fPAl2 )
  317.                             {
  318.                             fPAl3 = (long double**)NewHandle ( kInc * sizeof ( long double ) );
  319.                             
  320.                             if ( fPAl3 )
  321.                                 {
  322.                                 fAlloc = kInc;
  323.                                 **fXArray = xValue;
  324.                                 **fYArray = yValue;
  325.                                 fNumPoints = 1;
  326.                                 fSelectedPoint = 1;
  327.                                 }
  328.                             else
  329.                                 {
  330.                                 DisposHandle ( (Handle)fPAl2 );
  331.                                 fPAl2 = 0L;
  332.                                 DisposHandle ( (Handle)fPAl1 );
  333.                                 fPAl1 = 0L;
  334.                                 DisposHandle ( (Handle)fSlopeArray );
  335.                                 fSlopeArray = 0L;
  336.                                 DisposHandle ( (Handle)fXArray );
  337.                                 fXArray = 0L;
  338.                                 DisposHandle ( (Handle)fYArray );
  339.                                 fYArray = 0L;
  340.                                 index = -1;
  341.                                 }
  342.                             }
  343.                         else
  344.                             {
  345.                             DisposHandle ( (Handle)fPAl1 );
  346.                             fPAl1 = 0L;
  347.                             DisposHandle ( (Handle)fSlopeArray );
  348.                             fSlopeArray = 0L;
  349.                             DisposHandle ( (Handle)fXArray );
  350.                             fXArray = 0L;
  351.                             DisposHandle ( (Handle)fYArray );
  352.                             fYArray = 0L;
  353.                             index = -1;
  354.                             }
  355.                         }
  356.                     else
  357.                         {
  358.                         DisposHandle ( (Handle)fSlopeArray );
  359.                         fSlopeArray = 0L;
  360.                         DisposHandle ( (Handle)fXArray );
  361.                         fXArray = 0L;
  362.                         DisposHandle ( (Handle)fYArray );
  363.                         fYArray = 0L;
  364.                         index = -1;
  365.                         }
  366.                     }
  367.                 else
  368.                     {
  369.                     DisposHandle ( (Handle)fXArray );
  370.                     fXArray = 0L;
  371.                     DisposHandle ( (Handle)fYArray );
  372.                     fYArray = 0L;
  373.                     index = -1;
  374.                     }
  375.                 }
  376.             else
  377.                 {
  378.                 DisposHandle ( (Handle)fXArray );
  379.                 fXArray = 0L;
  380.                 index = -1;
  381.                 }
  382.             }
  383.         else
  384.             index = -1;
  385.         }
  386.     
  387.     return index + 1;
  388. }
  389.  
  390. /************************************************************************************************/
  391. /*        Function Name:        PointIsOnLine                                                                                */
  392. /*        Description:        Tests the given point to see if it's on the line                                */
  393. /*        Primary Author:    Chris Marshall                                                                                */
  394. /************************************************************************************************/
  395. /*                                                    MODIFICATION HISTORY                                                    */
  396. /************************************************************************************************/
  397. /*    Date            Author                Description                                                                        */
  398. /*                                                                                                                                */
  399. /************************************************************************************************/
  400. /*##############################################################################################*/
  401. /************************************************************************************************/
  402. /* radius is a "fuzzy area" that allows the point to be around the line, but not exactly on it.    */
  403. /* If radius is nonzero, then it describes a radius around the given point.  This is useful for    */
  404. /* hit testing mouse coordinates in something like a gamma table.                                            */
  405. /************************************************************************************************/
  406.  
  407. Boolean Spline::PointIsOnLine ( long & xValue, long & yValue )
  408. {
  409.     Boolean     isOn = false;
  410.     long        yVal = this->GetYValue ( xValue );
  411.     
  412.     if ( (yVal <= (yValue + fHitRadius)) && (yVal >= (yValue - fHitRadius)) )
  413.         isOn = true;
  414.     else
  415.         {
  416.         yVal = this->GetYValue ( xValue - fHitRadius );
  417.         if ( (yVal <= (yValue + fHitRadius)) && (yVal >= (yValue - fHitRadius)) )
  418.             {
  419.             xValue = xValue - fHitRadius;
  420.             isOn = true;
  421.             }
  422.         else
  423.             {
  424.             yVal = this->GetYValue ( xValue + fHitRadius );
  425.             if ( (yVal <= (yValue + fHitRadius)) && (yVal >= (yValue - fHitRadius)) )
  426.                 {
  427.                 xValue = xValue + fHitRadius;
  428.                 isOn = true;
  429.                 }
  430.             }
  431.         }
  432.     
  433.     if ( isOn )
  434.         yValue = yVal;
  435.     
  436.     return isOn;
  437. }
  438.  
  439. /************************************************************************************************/
  440. /*        Function Name:        IsASplinePoint                                                                                */
  441. /*        Description:        Tests the given point to see if it's on the line                                */
  442. /*        Primary Author:    Chris Marshall                                                                                */
  443. /************************************************************************************************/
  444. /*                                                    MODIFICATION HISTORY                                                    */
  445. /************************************************************************************************/
  446. /*    Date            Author                Description                                                                        */
  447. /*                                                                                                                                */
  448. /************************************************************************************************/
  449. /*##############################################################################################*/
  450. /************************************************************************************************/
  451. /* fHitRadius is a "fuzzy area" that lets the point be around the point, but not right on it.    */
  452. /* If it is nonzero, then it describes a radius around the given point.  This is useful for hit    */
  453. /* testing mouse coordinates in something like a gamma table.  xOnly is a flag that the caller    */
  454. /* sets if they just want to find out if the horizontal coordinate matches, but without             */
  455. /* checking the vertical coordinate.                                                                                */
  456. /************************************************************************************************/
  457.  
  458. short Spline::IsASplinePoint ( long & xValue, long & yValue, Boolean xOnly )
  459. {
  460.     short    ret = 0;
  461.     
  462.     if ( fNumPoints )
  463.         {
  464.         for ( short index = 0; index < fNumPoints; index++ )
  465.             {
  466.             if ( (xValue >= *(*fXArray + index) - fHitRadius)
  467.                 && (xValue <= *(*fXArray + index) + fHitRadius) )
  468.                 {
  469.                 xValue = *(*fXArray + index);
  470.                 
  471.                 if ( !xOnly )    // Have to be anal-retentive, and check the Y
  472.                     {
  473.                     if ( (yValue >= *(*fYArray + index) - fHitRadius)
  474.                         && (yValue <= *(*fYArray + index) + fHitRadius) )
  475.                         {
  476.                         yValue = *(*fYArray + index);
  477.                         ret = index + 1;
  478.                         break;
  479.                         }
  480.                     else    // Yeah, I know, it's real gross, but it's reasonably fast
  481.                         if ( (yValue >= *(*fYArray + index) - (fHitRadius >> 1))
  482.                             && (yValue <= *(*fYArray + index) + (fHitRadius >> 1)) )
  483.                             {
  484.                             yValue = *(*fYArray + index);
  485.                             ret = index + 1;
  486.                             break;
  487.                             }
  488.                     }
  489.                 else    // We're satisfied with just the X matching up
  490.                     {
  491.                     yValue = *(*fYArray + index);
  492.                     ret = index + 1;
  493.                     break;
  494.                     }
  495.                 }
  496.             }
  497.         }
  498.     
  499.     return ret;
  500. }
  501.  
  502. /************************************************************************************************/
  503. /*        Function Name:        PointIsBetween                                                                                */
  504. /*        Description:        Returns indexes of the spline points above and below the given point        */
  505. /*        Primary Author:    Chris Marshall                                                                                */
  506. /************************************************************************************************/
  507. /*                                                    MODIFICATION HISTORY                                                    */
  508. /************************************************************************************************/
  509. /*    Date            Author                Description                                                                        */
  510. /*                                                                                                                                */
  511. /************************************************************************************************/
  512. /*##############################################################################################*/
  513. /************************************************************************************************/
  514. /* boundary will tell you if the tested point is equal to one or the other points it is between    */
  515. /* on the x-axis.  boundary will be -1 if it is the point returned in below, 1 if it is the        */
  516. /* point returned in above, and 0 if it is not equal to either.                                            */
  517. /************************************************************************************************/
  518.  
  519. short Spline::PointIsBetween ( long xValue, short & above, short & below )
  520. {
  521.     short        boundary = 0;
  522.     register    short index = 0;
  523.     
  524.     below = -1;
  525.     above = -1;
  526.     
  527.     while ( (index < fNumPoints) && (xValue > (*(*fXArray + index) - fHitRadius)) ) index++;
  528.     
  529.     if ( index < fNumPoints )
  530.         {
  531.         if ( xValue == *(*fXArray + index) )
  532.             boundary = -1;
  533.         
  534.         if ( xValue >= *(*fXArray + index) )
  535.             below = index + 1;
  536.         }
  537.     
  538.     for ( index = fNumPoints; index-- && (xValue < *(*fXArray + index)); )
  539.         { /* So the $#@!! compiler doesn't give us a warning! */ };
  540.     
  541.     if ( index >= 0 )
  542.         {
  543.         if ( xValue == *(*fXArray + index) )
  544.             boundary = 1;
  545.         
  546.         if ( xValue <= *(*fXArray + index) )
  547.             above = index + 1;
  548.         }
  549.     
  550.     return boundary;    // Return a value indicating that the value is equal to one of the points
  551. }
  552.  
  553. /************************************************************************************************/
  554. /*        Function Name:        GetSplinePoint                                                                                */
  555. /*        Description:        Returns the coordinates of an indexed spline point                                */
  556. /*        Primary Author:    Chris Marshall                                                                                */
  557. /************************************************************************************************/
  558. /*                                                    MODIFICATION HISTORY                                                    */
  559. /************************************************************************************************/
  560. /*    Date            Author                Description                                                                        */
  561. /*                                                                                                                                */
  562. /************************************************************************************************/
  563. /*##############################################################################################*/
  564. /************************************************************************************************/
  565.  
  566. short Spline::GetSplinePoint ( short index, long & xValue, long & yValue )
  567. {
  568.     if ( index && (index <= fNumPoints) )
  569.         {
  570.         xValue = *(*fXArray + (index - 1));
  571.         yValue = *(*fYArray + (index - 1));
  572.         }
  573.     else
  574.         {
  575.         xValue = -1;
  576.         yValue = -1;
  577.         }
  578.     
  579.     return index;
  580. }
  581.  
  582. /************************************************************************************************/
  583. /*        Function Name:        DeleteSplinePoint                                                                            */
  584. /*        Description:        Takes a spline point out of the list                                                */
  585. /*        Primary Author:    Chris Marshall                                                                                */
  586. /************************************************************************************************/
  587. /*                                                    MODIFICATION HISTORY                                                    */
  588. /************************************************************************************************/
  589. /*    Date            Author                Description                                                                        */
  590. /*                                                                                                                                */
  591. /************************************************************************************************/
  592. /*##############################################################################################*/
  593. /************************************************************************************************/
  594.  
  595. void Spline::DeleteSplinePoint ( short index )
  596. {
  597.     if ( index && (index <= fNumPoints) )
  598.         {
  599.         long size = (fNumPoints - index) * sizeof ( long );
  600.         long sizeS = (fNumPoints - index) * sizeof ( long double );
  601.         
  602.         if ( size )
  603.             {
  604.             BlockMove ( (*fXArray + index), (*fXArray + (index - 1)), size );
  605.             BlockMove ( (*fYArray + index), (*fYArray + (index - 1)), size );
  606.             BlockMove ( (*fSlopeArray + index), (*fSlopeArray + (index - 1)), sizeS );
  607.             }
  608.         
  609.         size = --fNumPoints * sizeof ( long );
  610.         sizeS = fNumPoints * sizeof ( long double );
  611.         
  612.         if ( size )
  613.             {
  614.             SetHandleSize ( (Handle)fXArray, size );
  615.             if ( MemError ( ) == noErr )
  616.                 SetHandleSize ( (Handle)fYArray, size );
  617.             if ( MemError ( ) == noErr )
  618.                 SetHandleSize ( (Handle)fSlopeArray, sizeS );
  619.             if ( MemError ( ) == noErr )
  620.                 this->CreateCoefficients ( );
  621.             }
  622.         else
  623.             {
  624.             DisposHandle ( (Handle)fXArray );
  625.             fXArray = 0L;
  626.             DisposHandle ( (Handle)fYArray );
  627.             fYArray = 0L;
  628.             DisposHandle ( (Handle)fSlopeArray );
  629.             fSlopeArray = 0L;
  630.             DisposHandle ( (Handle)fPAl3 );
  631.             fPAl3 = 0L;
  632.             DisposHandle ( (Handle)fPAl2 );
  633.             fPAl2 = 0L;
  634.             DisposHandle ( (Handle)fPAl1 );
  635.             fPAl1 = 0L;
  636.             }
  637.         
  638.         if ( fSelectedPoint > index )
  639.             fSelectedPoint--;
  640.         else
  641.             if ( (fSelectedPoint == index) && (index > 2) )
  642.                 fSelectedPoint = index - 1;
  643.         }
  644. }
  645.  
  646. /************************************************************************************************/
  647. /*        Function Name:        ChangeSplinePoint                                                                            */
  648. /*        Description:        Alters the value of a spline point, replacing it if necessary                */
  649. /*        Primary Author:    Chris Marshall                                                                                */
  650. /************************************************************************************************/
  651. /*                                                    MODIFICATION HISTORY                                                    */
  652. /************************************************************************************************/
  653. /*    Date            Author                Description                                                                        */
  654. /*                                                                                                                                */
  655. /************************************************************************************************/
  656. /*##############################################################################################*/
  657. /************************************************************************************************/
  658.  
  659. void Spline::ChangeSplinePoint ( short & index, long xValue, long yValue )
  660. {
  661.     register short count;
  662.     long        domainL, domainH;
  663.     
  664.     if ( index > 1 )
  665.         domainL = *(*fXArray + (index - 2));
  666.     else
  667.         domainL = xValue - 1;
  668.     
  669.     if ( index < fNumPoints )
  670.         domainH = *(*fXArray + index);
  671.     else
  672.         domainH = xValue + 1;
  673.         
  674.     fSelectedPoint = index;
  675.  
  676.     if ( (xValue > domainL) && (xValue < domainH) )
  677.         {
  678.         *(*fXArray + (index - 1)) = xValue;
  679.         *(*fYArray + (index - 1)) = yValue;
  680.         this->CreateCoefficients ( );
  681.         }
  682.     else
  683.         if ( !this->IsASplinePoint ( xValue, yValue, true ) )
  684.             {
  685.             this->DeleteSplinePoint ( index );
  686.             index = this->AddSplinePoint ( xValue, yValue );
  687.             }
  688. }
  689.  
  690. /************************************************************************************************/
  691. /*        Function Name:        GetYValue                                                                                    */
  692. /*        Description:        Returns a Y value along a spline curve described by coefficients            */
  693. /*        Primary Author:    Tom Knoll, Khouri Giordano & Chris Marshall                                        */
  694. /************************************************************************************************/
  695. /*                                                    MODIFICATION HISTORY                                                    */
  696. /************************************************************************************************/
  697. /*    Date            Author                Description                                                                        */
  698. /*                                                                                                                                */
  699. /************************************************************************************************/
  700. /*##############################################################################################*/
  701. /************************************************************************************************/
  702.  
  703. long Spline::GetYValue ( long xValue )
  704. {
  705.     register short            count = 1;
  706.     register long double    loPerc, hiPerc;
  707.     register long            ret = 0L, deltaX;
  708.     
  709.     if ( !fNumPoints )
  710.         return 0;
  711.     
  712.     if ( xValue < **fXArray )
  713.         return ( **fYArray );
  714.     
  715.     if ( xValue > *(*fXArray + (fNumPoints - 1)) )
  716.         return ( *(*fYArray + (fNumPoints - 1)) );
  717.     
  718.     if ( fNumPoints > 2 )
  719.         {
  720.         while ( (count < fNumPoints) && (xValue > *(*fXArray + count)) ) count++;
  721.         
  722.         deltaX = *(*fXArray + count) - *(*fXArray + (count - 1));
  723.         loPerc = (long double)(xValue - *(*fXArray + (count - 1))) / (long double)deltaX;
  724.         hiPerc = (long double)(*(*fXArray + count) - xValue) / (long double)deltaX;
  725.         
  726.         ret = (long)(*(*fYArray + (count - 1)) * (2.0 - hiPerc + loPerc) + *(*fSlopeArray
  727.                 + (count - 1)) * (long double)deltaX * loPerc) * hiPerc * hiPerc
  728.                 + (*(*fYArray + count) * (2.0 - loPerc + hiPerc) - *(*fSlopeArray + count)
  729.                 * (long double)deltaX * hiPerc) * loPerc * loPerc;
  730.         }
  731.     else    // Fast straight line if we only have two points
  732.         if ( fNumPoints == 2 )
  733.             ret = ((((xValue - **fXArray) * (*(*fYArray + 1) - **fYArray))
  734.                     / (*(*fXArray + 1) - **fXArray)) + **fYArray);
  735.         else
  736.             if ( fNumPoints == 1 )
  737.                 ret = **fYArray;
  738.     
  739.     return ret;
  740. }
  741.  
  742. /************************************************************************************************/
  743. /*        Function Name:        GetRealYValue                                                                                */
  744. /*        Description:        Returns a Y value as a real number (slower, but more accurate)                */
  745. /*        Primary Author:    Tom Knoll, Khouri Giordano & Chris Marshall                                        */
  746. /************************************************************************************************/
  747. /*                                                    MODIFICATION HISTORY                                                    */
  748. /************************************************************************************************/
  749. /*    Date            Author                Description                                                                        */
  750. /*                                                                                                                                */
  751. /************************************************************************************************/
  752. /*##############################################################################################*/
  753. /************************************************************************************************/
  754.  
  755. long double Spline::GetRealYValue ( long double xValue )
  756. {
  757.     register short            count = 1;
  758.     register long double    loPerc, hiPerc, ret = 0L, deltaX;
  759.     
  760.     if ( !fNumPoints )
  761.         return 0;
  762.     
  763.     if ( xValue < (long double)**fXArray )
  764.         ret = (long double)**fYArray;
  765.     else
  766.         {
  767.         if ( xValue > (long double)*(*fXArray + (fNumPoints - 1)) )
  768.             ret = (long double)*(*fYArray + (fNumPoints - 1));
  769.         else
  770.             if ( fNumPoints > 2 )
  771.                 {
  772.                 while ( (count < fNumPoints) && (xValue > *(*fXArray + count)) ) count++;
  773.                 
  774.                 deltaX = (long double)*(*fXArray + count) - *(*fXArray + (count - 1));
  775.                 loPerc = (xValue - (long double)*(*fXArray + (count - 1))) / deltaX;
  776.                 hiPerc = ((long double)*(*fXArray + count) - xValue) / deltaX;
  777.                 
  778.                 ret = (*(*fYArray + (count - 1)) * (2.0 - hiPerc + loPerc) + *(*fSlopeArray
  779.                         + (count - 1)) * deltaX * loPerc) * hiPerc * hiPerc
  780.                         + (*(*fYArray + count) * (2.0 - loPerc + hiPerc) - *(*fSlopeArray + count)
  781.                         * deltaX * hiPerc) * loPerc * loPerc;
  782.                 }
  783.             else    // Fast straight line if we only have two points
  784.                 if ( fNumPoints == 2 )
  785.                     ret = ((((xValue - **fXArray) * (*(*fYArray + 1) - **fYArray))
  786.                             / (*(*fXArray + 1) - **fXArray)) + **fYArray);
  787.                 else
  788.                     if ( fNumPoints == 1 )
  789.                         ret = (long double)**fYArray;
  790.         }
  791.     
  792.     return ret;
  793. }
  794.  
  795. /************************************************************************************************/
  796. /*        Function Name:        FixedSpline                                                                                    */
  797. /*        Description:        Initializes the object, and sets two locked endpoints                            */
  798. /*        Primary Author:    Tom Knoll, Khouri Giordano & Chris Marshall                                        */
  799. /************************************************************************************************/
  800. /*                                                    MODIFICATION HISTORY                                                    */
  801. /************************************************************************************************/
  802. /*    Date            Author                Description                                                                        */
  803. /*                                                                                                                                */
  804. /************************************************************************************************/
  805. /*##############################################################################################*/
  806. /************************************************************************************************/
  807.  
  808. FixedSpline::FixedSpline ( long x0, long y0, long x1, long y1, long hitRadius )
  809. {
  810.     this->Initialize ( );
  811.     this->AddSplinePoint ( x0, y0 );
  812.     this->AddSplinePoint ( x1, y1 );
  813.     fHitRadius = hitRadius;
  814. }
  815.  
  816. /************************************************************************************************/
  817. /*        Function Name:        CreateSplineCoefficients                                                                */
  818. /*        Description:        Calculates a table of spline coefficients for caculating a spline curve    */
  819. /*        Primary Author:    Tom Knoll, Khouri Giordano & Chris Marshall                                        */
  820. /************************************************************************************************/
  821. /*                                                    MODIFICATION HISTORY                                                    */
  822. /************************************************************************************************/
  823. /*    Date            Author                Description                                                                        */
  824. /*                                                                                                                                */
  825. /*    09/30/93        Chris Marshall        I fixed a little bug in the coefficient calculator that made    */
  826. /*                                            the curve just the teensiest bit WRONG.                                */
  827. /*                                                                                                                                */
  828. /************************************************************************************************/
  829. /*##############################################################################################*/
  830. /************************************************************************************************/
  831.  
  832. void FixedSpline::CreateCoefficients ( )
  833. {
  834.     register short    count;
  835.     register Fixed    lastSlope, slope, lastDeltaX, deltaX, work;
  836.     
  837.     if ( !fNumPoints )
  838.         return;
  839.  
  840.     fNumPoints--;    // "Neck down" our point count by one
  841.  
  842.     lastDeltaX = (*(*fXArray + 1) - **fXArray) << 16;
  843.     **fFixedArray = lastSlope = FixDiv ( (*(*fYArray + 1) - **fYArray) << 16, lastDeltaX );
  844.     
  845.     for ( count = 2; count <= fNumPoints; ++count )
  846.         {
  847.         deltaX = (*(*fXArray + count) - *(*fXArray + (count - 1))) << 16;
  848.         slope = FixDiv ( (*(*fYArray + count) - *(*fYArray + (count - 1))) << 16, deltaX );
  849.         
  850.         *(*fFixedArray + (count - 1)) = FixDiv ( FixMul ( lastSlope, deltaX )
  851.                                                             + FixMul ( slope, lastDeltaX ),
  852.                                                             (lastDeltaX + deltaX) );
  853.         
  854.         lastDeltaX = deltaX;
  855.         lastSlope = slope;
  856.         }
  857.     
  858.     *(*fFixedArray + fNumPoints) = (lastSlope << 1) - *(*fFixedArray + (fNumPoints - 1));
  859.     **fFixedArray = (**fFixedArray << 1) - *(*fFixedArray + 1);
  860.     
  861.     if ( fNumPoints > 2 )    // If we have more than three points, we invent endpoint derivatives
  862.         {
  863.         **fPAf2 = *(*fPAf1 + fNumPoints) = 0x00008000;
  864.         **fPAf3 = FixMul ( 0x0000C000, (**fFixedArray + *(*fFixedArray + 1)) );
  865.         *(*fPAf3 + fNumPoints) = FixMul ( 0x0000C000, (*(*fFixedArray + (fNumPoints - 1))
  866.                                                     + *(*fFixedArray + fNumPoints)) );
  867.         
  868.         for ( count = 1; count <= fNumPoints; ++count)
  869.             {
  870.             if ( count < fNumPoints )
  871.                 {
  872.                 work = (*(*fXArray + (count + 1)) - *(*fXArray + (count - 1))) << 17;
  873.                 *(*fPAf1 + count) = FixDiv ( (*(*fXArray + (count + 1)) - *(*fXArray + count)) << 16,
  874.                                                         work );
  875.                 // Okay, I tried this code is back
  876.                 *(*fPAf2 + count) = FixDiv ( (*(*fXArray + count) - *(*fXArray + (count - 1))) << 16,
  877.                                                         work );
  878.                 *(*fPAf3 + count) = *(*fFixedArray + count) + (*(*fFixedArray + count) >> 1);
  879.                 }
  880.             
  881.             work = 0x00010000 - FixMul ( *(*fPAf2 + (count - 1)), *(*fPAf1 + count) );
  882.             
  883.             if ( count < fNumPoints )
  884.                 *(*fPAf2 + count) = FixDiv ( *(*fPAf2 + count), work );
  885.             
  886.             *(*fPAf3 + count) = FixDiv ( *(*fPAf3 + count)
  887.                 - FixMul ( *(*fPAf3 + (count - 1)), *(*fPAf1 + count) ), work );
  888.             }
  889.         
  890.         for ( count = fNumPoints - 1; count >= 0; count-- )
  891.             *(*fFixedArray + count) = *(*fPAf3 + count) - FixMul ( *(*fPAf2 + count),
  892.                                                 *(*fPAf3 + (count + 1)) );
  893.         
  894.         *(*fFixedArray + fNumPoints) = *(*fPAf3 + fNumPoints);
  895.         }
  896.     
  897.     fNumPoints++;
  898. }
  899.  
  900. /************************************************************************************************/
  901. /*        Function Name:        Initialize                                                                                    */
  902. /*        Description:        Initializes the class' variables                                                        */
  903. /*        Primary Author:    Tom Knoll, Khouri Giordano & Chris Marshall                                        */
  904. /************************************************************************************************/
  905. /*                                                    MODIFICATION HISTORY                                                    */
  906. /************************************************************************************************/
  907. /*    Date            Author                Description                                                                        */
  908. /*                                                                                                                                */
  909. /************************************************************************************************/
  910. /*##############################################################################################*/
  911. /************************************************************************************************/
  912.  
  913. void FixedSpline::Initialize ( )
  914. {
  915.     fFixedArray = 0L;
  916.     fPAf1 = fPAf2 = fPAf3 = 0L;
  917. }
  918.  
  919. /************************************************************************************************/
  920. /*        Function Name:        ~FixedSpline                                                                                */
  921. /*        Description:        Deallocates the array upon destruction of the object                            */
  922. /*        Primary Author:    Chris Marshall                                                                                */
  923. /************************************************************************************************/
  924. /*                                                    MODIFICATION HISTORY                                                    */
  925. /************************************************************************************************/
  926. /*    Date            Author                Description                                                                        */
  927. /*                                                                                                                                */
  928. /************************************************************************************************/
  929. /*##############################################################################################*/
  930. /************************************************************************************************/
  931.  
  932. FixedSpline::~FixedSpline ( )
  933. {
  934.     if ( fFixedArray )
  935.         DisposHandle ( (Handle)fFixedArray );
  936.     if ( fPAf3 )
  937.         DisposHandle ( (Handle)fPAf3 );
  938.     if ( fPAf2 )
  939.         DisposHandle ( (Handle)fPAf2 );
  940.     if ( fPAf1 )
  941.         DisposHandle ( (Handle)fPAf1 );
  942.     if ( fXArray )
  943.         DisposHandle ( (Handle)fXArray );
  944.     fXArray = 0L;
  945.     if ( fYArray )
  946.         DisposHandle ( (Handle)fYArray );
  947.     fYArray = 0L;
  948. }
  949.  
  950. /************************************************************************************************/
  951. /*        Function Name:        AddSplinePoint                                                                                */
  952. /*        Description:        Adds a point to the list of points, and recalculates the coefficients    */
  953. /*        Primary Author:    Chris Marshall                                                                                */
  954. /************************************************************************************************/
  955. /*                                                    MODIFICATION HISTORY                                                    */
  956. /************************************************************************************************/
  957. /*    Date            Author                Description                                                                        */
  958. /*                                                                                                                                */
  959. /************************************************************************************************/
  960. /*##############################################################################################*/
  961. /************************************************************************************************/
  962.  
  963. short FixedSpline::AddSplinePoint ( long xValue, long yValue )
  964. {
  965.     short index = 0;
  966.     long    size = (fNumPoints + 1) * sizeof ( long );
  967.     long    sizeS = (fNumPoints + 1) * sizeof ( Fixed );
  968.     
  969.     if ( fNumPoints )
  970.         {
  971.         if ( !(index = this->IsASplinePoint ( xValue, yValue, true )) )
  972.             {
  973.             while ( (index < fNumPoints) && (xValue > *(*fXArray + index)) ) index++;
  974.             
  975.             if ( (index == fNumPoints) || (xValue != *(*fXArray + index)) )
  976.                 {
  977.                 SetHandleSize ( (Handle)fXArray, size );
  978.                 
  979.                 if ( MemError ( ) == noErr )
  980.                     SetHandleSize ( (Handle)fYArray, size );
  981.                 
  982.                 if ( MemError ( ) == noErr )
  983.                     SetHandleSize ( (Handle)fFixedArray, sizeS );
  984.                 
  985.                 if ( MemError ( ) == noErr )
  986.                     {
  987.                     size = (fNumPoints - index) * sizeof ( long );
  988.                     sizeS = (fNumPoints - index) * sizeof ( Fixed );
  989.                     
  990.                     if ( size )
  991.                         {
  992.                         BlockMove ( (*fXArray + index), (*fXArray + 1 + index), size );
  993.                         BlockMove ( (*fYArray + index), (*fYArray + 1 + index), size );
  994.                         BlockMove ( (*fFixedArray + index), (*fFixedArray + 1 + index), sizeS );
  995.                         }
  996.                     
  997.                     *(*fXArray + index) = xValue;
  998.                     *(*fYArray + index) = yValue;
  999.                     
  1000.                     fNumPoints++;
  1001.                     
  1002.                     fSelectedPoint = index + 1;
  1003.                     
  1004.                     // We need to add another block to our working buffers
  1005.                     if ( (fNumPoints > fAlloc) && fPAf1 && fPAf2 && fPAf3 )
  1006.                         {
  1007.                         fAlloc += kInc;
  1008.                         sizeS = fAlloc * sizeof ( Fixed );
  1009.                         
  1010.                         SetHandleSize ( (Handle)fPAf1, sizeS );
  1011.                         
  1012.                         if ( MemError ( ) == noErr )
  1013.                             SetHandleSize ( (Handle)fPAf2, sizeS );
  1014.                         
  1015.                         if ( MemError ( ) == noErr )
  1016.                             SetHandleSize ( (Handle)fPAf3, sizeS );
  1017.                         }
  1018.                     
  1019.                     this->CreateCoefficients ( );
  1020.                     }
  1021.                 else
  1022.                     index = -1;
  1023.                 }
  1024.             else
  1025.                 {
  1026.                 fSelectedPoint = index + 1;
  1027.                 *(*fYArray + index) = yValue;
  1028.                 }
  1029.             }
  1030.         else
  1031.             fSelectedPoint = index + 1;
  1032.         }
  1033.     else
  1034.         {
  1035.         fXArray = (long**) NewHandle ( size );
  1036.         
  1037.         if ( fXArray )
  1038.             {
  1039.             fYArray = (long**) NewHandle ( size );
  1040.             
  1041.             if ( fYArray )
  1042.                 {
  1043.                 fFixedArray = (Fixed**) NewHandle ( sizeS );
  1044.                 
  1045.                 if ( fFixedArray )
  1046.                     {
  1047.                     fPAf1 = (Fixed**)NewHandle ( kInc * sizeof ( Fixed ) );
  1048.                     
  1049.                     if ( fPAf1 )
  1050.                         {
  1051.                         fPAf2 = (Fixed**)NewHandle ( kInc * sizeof ( Fixed ) );
  1052.                         
  1053.                         if ( fPAf2 )
  1054.                             {
  1055.                             fPAf3 = (Fixed**)NewHandle ( kInc * sizeof ( Fixed ) );
  1056.                             
  1057.                             if ( fPAf3 )
  1058.                                 {
  1059.                                 fAlloc = kInc;
  1060.                                 **fXArray = xValue;
  1061.                                 **fYArray = yValue;
  1062.                                 fNumPoints = 1;
  1063.                                 fSelectedPoint = 1;
  1064.                                 }
  1065.                             else
  1066.                                 {
  1067.                                 DisposHandle ( (Handle)fPAf2 );
  1068.                                 fPAf2 = 0L;
  1069.                                 DisposHandle ( (Handle)fPAf1 );
  1070.                                 fPAf1 = 0L;
  1071.                                 DisposHandle ( (Handle)fFixedArray );
  1072.                                 fFixedArray = 0L;
  1073.                                 DisposHandle ( (Handle)fXArray );
  1074.                                 fXArray = 0L;
  1075.                                 DisposHandle ( (Handle)fYArray );
  1076.                                 fYArray = 0L;
  1077.                                 index = -1;
  1078.                                 }
  1079.                             }
  1080.                         else
  1081.                             {
  1082.                             DisposHandle ( (Handle)fPAf1 );
  1083.                             fPAf1 = 0L;
  1084.                             DisposHandle ( (Handle)fFixedArray );
  1085.                             fFixedArray = 0L;
  1086.                             DisposHandle ( (Handle)fXArray );
  1087.                             fXArray = 0L;
  1088.                             DisposHandle ( (Handle)fYArray );
  1089.                             fYArray = 0L;
  1090.                             index = -1;
  1091.                             }
  1092.                         }
  1093.                     else
  1094.                         {
  1095.                         DisposHandle ( (Handle)fFixedArray );
  1096.                         fFixedArray = 0L;
  1097.                         DisposHandle ( (Handle)fXArray );
  1098.                         fXArray = 0L;
  1099.                         DisposHandle ( (Handle)fYArray );
  1100.                         fYArray = 0L;
  1101.                         index = -1;
  1102.                         }
  1103.                     }
  1104.                 else
  1105.                     {
  1106.                     DisposHandle ( (Handle)fXArray );
  1107.                     fXArray = 0L;
  1108.                     DisposHandle ( (Handle)fYArray );
  1109.                     fYArray = 0L;
  1110.                     index = -1;
  1111.                     }
  1112.                 }
  1113.             else
  1114.                 {
  1115.                 DisposHandle ( (Handle)fXArray );
  1116.                 fXArray = 0L;
  1117.                 index = -1;
  1118.                 }
  1119.             }
  1120.         else
  1121.             index = -1;
  1122.         }
  1123.     
  1124.     return index + 1;
  1125. }
  1126.  
  1127. /************************************************************************************************/
  1128. /*        Function Name:        DeleteSplinePoint                                                                            */
  1129. /*        Description:        Takes a spline point out of the list                                                */
  1130. /*        Primary Author:    Chris Marshall                                                                                */
  1131. /************************************************************************************************/
  1132. /*                                                    MODIFICATION HISTORY                                                    */
  1133. /************************************************************************************************/
  1134. /*    Date            Author                Description                                                                        */
  1135. /*                                                                                                                                */
  1136. /************************************************************************************************/
  1137. /*##############################################################################################*/
  1138. /************************************************************************************************/
  1139.  
  1140. void FixedSpline::DeleteSplinePoint ( short index )
  1141. {
  1142.     if ( index && (index <= fNumPoints) )
  1143.         {
  1144.         long size = (fNumPoints - index) * sizeof ( long );
  1145.         long sizeS = (fNumPoints - index) * sizeof ( Fixed );
  1146.         
  1147.         if ( size )
  1148.             {
  1149.             BlockMove ( (*fXArray + index), (*fXArray + (index - 1)), size );
  1150.             BlockMove ( (*fYArray + index), (*fYArray + (index - 1)), size );
  1151.             BlockMove ( (*fFixedArray + index), (*fFixedArray + (index - 1)), sizeS );
  1152.             }
  1153.         
  1154.         size = --fNumPoints * sizeof ( long );
  1155.         sizeS = fNumPoints * sizeof ( Fixed );
  1156.         
  1157.         if ( size )
  1158.             {
  1159.             SetHandleSize ( (Handle)fXArray, size );
  1160.             if ( MemError ( ) == noErr )
  1161.                 SetHandleSize ( (Handle)fYArray, size );
  1162.             if ( MemError ( ) == noErr )
  1163.                 SetHandleSize ( (Handle)fFixedArray, sizeS );
  1164.             if ( MemError ( ) == noErr )
  1165.                 this->CreateCoefficients ( );
  1166.             }
  1167.         else
  1168.             {
  1169.             DisposHandle ( (Handle)fXArray );
  1170.             fXArray = 0L;
  1171.             DisposHandle ( (Handle)fYArray );
  1172.             fYArray = 0L;
  1173.             DisposHandle ( (Handle)fFixedArray );
  1174.             fFixedArray = 0L;
  1175.             DisposHandle ( (Handle)fPAf3 );
  1176.             fPAf3 = 0L;
  1177.             DisposHandle ( (Handle)fPAf2 );
  1178.             fPAf2 = 0L;
  1179.             DisposHandle ( (Handle)fPAf1 );
  1180.             fPAf1 = 0L;
  1181.             }
  1182.         
  1183.         if ( fSelectedPoint > index )
  1184.             fSelectedPoint--;
  1185.         else
  1186.             if ( (fSelectedPoint == index) && (index > 2) )
  1187.                 fSelectedPoint = index - 1;
  1188.         }
  1189. }
  1190.  
  1191. /************************************************************************************************/
  1192. /*        Function Name:        GetFixYValue                                                                                */
  1193. /*        Description:        Returns a Y value along a spline curve described by coefficients            */
  1194. /*        Primary Author:    Tom Knoll, Khouri Giordano & Chris Marshall                                        */
  1195. /************************************************************************************************/
  1196. /*                                                    MODIFICATION HISTORY                                                    */
  1197. /************************************************************************************************/
  1198. /*    Date            Author                Description                                                                        */
  1199. /*                                                                                                                                */
  1200. /************************************************************************************************/
  1201. /*##############################################################################################*/
  1202. /************************************************************************************************/
  1203.  
  1204. Fixed FixedSpline::GetFixYValue ( Fixed xValue )
  1205. {
  1206.     register short        count = 1;
  1207.     register Fixed        loPerc, hiPerc, deltaX, x1, x_1, y1, y_1;
  1208.     Fixed                    ret;
  1209.     register long        xComp = Fix2Long ( xValue );
  1210.     
  1211.     if ( !fNumPoints )
  1212.         return 0;
  1213.     
  1214.     if ( (xComp < **fXArray) || (fNumPoints == 1) )
  1215.         return **fYArray << 16;
  1216.     
  1217.     if ( xComp > *(*fXArray + (fNumPoints - 1)) )
  1218.         return *(*fYArray + (fNumPoints - 1)) << 16;
  1219.     
  1220.     while ( (count < fNumPoints) && (xComp > *(*fXArray + count)) ) count++;
  1221.     
  1222.     x1 = *(*fXArray + count) << 16;
  1223.     x_1 = *(*fXArray + (count - 1)) << 16;
  1224.     
  1225.     deltaX = x1 - x_1;
  1226.     loPerc = FixDiv ( xValue - x_1, deltaX );
  1227.     hiPerc = FixDiv ( x1 - xValue, deltaX );
  1228.     
  1229.     if ( fNumPoints == 2 )    // Fast straight line for 2 points
  1230.         ret = ((((xComp - **fXArray) * (*(*fYArray + 1) - **fYArray))
  1231.                 / (*(*fXArray + 1) - **fXArray)) + **fYArray) << 16;
  1232.     else
  1233.         // Don't even try to decipher this line of spaghetti!
  1234.         ret = FixMul ( FixMul ( *(*fYArray + (count - 1)) << 16, (0x00020000 - hiPerc + loPerc) )
  1235.                 + FixMul ( *(*fFixedArray + (count - 1)), FixMul ( deltaX, loPerc ) ),
  1236.                 FixMul ( hiPerc, hiPerc ) ) + FixMul ( FixMul ( *(*fYArray + count) << 16,
  1237.                 (0x00020000 - loPerc + hiPerc) ) - FixMul ( *(*fFixedArray + count),
  1238.                 FixMul ( deltaX, hiPerc ) ), FixMul ( loPerc, loPerc ) );
  1239.     
  1240.     return ret;
  1241. }
  1242.  
  1243. /************************************************************************************************/
  1244.